#include	"Vector2d.h"
#include	"Vector2f.h"
#include	"Vector2i.h"
#include	<cmath>

const double Vector2d::EPSILON = 0.00001;

Vector2d::Vector2d()
{
}

Vector2d::Vector2d(double x, double y)
{
	Set(x, y);
}

Vector2d::Vector2d(float x, float y)
{
	Set(x, y);
}

Vector2d::Vector2d(int x, int y)
{
	Set(x, y);
}

Vector2d::Vector2d(const Vector2d & vec)
{
	Set(vec);
}

Vector2d::Vector2d(const Vector2f & vec)
{
	Set(vec);
}

Vector2d::Vector2d(const Vector2i & vec)
{
	Set(vec);
}

Vector2d::Vector2d(const double * arr)
{
	Set(arr);
}

Vector2d::Vector2d(const float * arr)
{
	Set(arr);
}

Vector2d::Vector2d(const int * arr)
{
	Set(arr);
}

Vector2d::~Vector2d()
{
}

void Vector2d::Set(double x, double y)
{
	m_data[0] = x;
	m_data[1] = y;
}

void Vector2d::Set(float x, float y)
{
	m_data[0] = double(x);
	m_data[1] = double(y);
}

void Vector2d::Set(int x, int y)
{
	m_data[0] = double(x);
	m_data[1] = double(y);
}

void Vector2d::Set(const double * arr)
{
	m_data[0] = arr[0];
	m_data[1] = arr[1];
}

void Vector2d::Set(const float * arr)
{
	m_data[0] = double(arr[0]);
	m_data[1] = double(arr[1]);
}

void Vector2d::Set(const int * arr)
{
	m_data[0] = double(arr[0]);
	m_data[1] = double(arr[1]);
}

Vector2d::operator const double*() const
{
	return m_data;
}

Vector2d::operator double*()
{
	return m_data;
}

const Vector2d & Vector2d::operator+() const
{
	return *this;
}

Vector2d & Vector2d::operator+()
{
	return *this;
}

Vector2d Vector2d::operator-() const
{
	return Vector2d(-m_data[0], -m_data[1]);
}

Vector2d & Vector2d::operator=(const Vector2d & vec)
{
	Set(vec);
	return *this;
}

Vector2d & Vector2d::operator=(const Vector2f & vec)
{
	Set(vec);
	return *this;
}

Vector2d & Vector2d::operator=(const Vector2i & vec)
{
	Set(vec);
	return *this;
}

Vector2d & Vector2d::operator+=(const Vector2d & vec)
{
	Set(m_data[0] + vec[0], m_data[1] + vec[1]);
	return *this;
}

Vector2d & Vector2d::operator+=(const Vector2f & vec)
{
	Set(m_data[0] + vec[0], m_data[1] + vec[1]);
	return *this;
}

Vector2d & Vector2d::operator+=(const Vector2i & vec)
{
	Set(m_data[0] + vec[0], m_data[1] + vec[1]);
	return *this;
}

Vector2d & Vector2d::operator-=(const Vector2d & vec)
{
	Set(m_data[0] - vec[0], m_data[1] - vec[1]);
	return *this;
}

Vector2d & Vector2d::operator-=(const Vector2f & vec)
{
	Set(m_data[0] - vec[0], m_data[1] - vec[1]);
	return *this;
}

Vector2d & Vector2d::operator-=(const Vector2i & vec)
{
	Set(m_data[0] - vec[0], m_data[1] - vec[1]);
	return *this;
}

Vector2d & Vector2d::operator*=(double num)
{
	Set(m_data[0] * num, m_data[1] * num);
	return *this;
}

Vector2d & Vector2d::operator*=(float num)
{
	Set(m_data[0] * num, m_data[1] * num);
	return *this;
}

Vector2d & Vector2d::operator*=(int num)
{
	Set(m_data[0] * num, m_data[1] * num);
	return *this;
}

Vector2d & Vector2d::operator/=(double num)
{
	Set(m_data[0] / num, m_data[1] / num);
	return *this;
}

Vector2d & Vector2d::operator/=(float num)
{
	Set(m_data[0] / num, m_data[1] / num);
	return *this;
}

Vector2d & Vector2d::operator/=(int num)
{
	Set(m_data[0] / num, m_data[1] / num);
	return *this;
}

Vector2d Vector2d::operator+(const Vector2d & vec) const
{
	return Vector2d(m_data[0] + vec[0], m_data[1] + vec[1]);
}

Vector2d Vector2d::operator+(const Vector2f & vec) const
{
	return Vector2d(m_data[0] + vec[0], m_data[1] + vec[1]);
}

Vector2d Vector2d::operator+(const Vector2i & vec) const
{
	return Vector2d(m_data[0] + vec[0], m_data[1] + vec[1]);
}

Vector2d Vector2d::operator-(const Vector2d & vec) const
{
	return Vector2d(m_data[0] - vec[0], m_data[1] - vec[1]);
}

Vector2d Vector2d::operator-(const Vector2f & vec) const
{
	return Vector2d(m_data[0] - vec[0], m_data[1] - vec[1]);
}

Vector2d Vector2d::operator-(const Vector2i & vec) const
{
	return Vector2d(m_data[0] - vec[0], m_data[1] - vec[1]);
}

Vector2d Vector2d::operator*(double num) const
{
	return Vector2d(m_data[0] * num, m_data[1] * num);
}

Vector2d Vector2d::operator*(float num) const
{
	return Vector2d(m_data[0] * num, m_data[1] * num);
}

Vector2d Vector2d::operator*(int num) const
{
	return Vector2d(m_data[0] * num, m_data[1] * num);
}

Vector2d Vector2d::operator/(double num) const
{
	return Vector2d(m_data[0] / num, m_data[1] / num);
}

Vector2d Vector2d::operator/(float num) const
{
	return Vector2d(m_data[0] / num, m_data[1] / num);
}

Vector2d Vector2d::operator/(int num) const
{
	return Vector2d(m_data[0] / num, m_data[1] / num);
}

Vector2d operator*(double num, const Vector2d & vec)
{
	return Vector2d(vec[0] * num, vec[1] * num);
}

Vector2d operator*(float num, const Vector2d & vec)
{
	return Vector2d(vec[0] * num, vec[1] * num);
}

Vector2d operator*(int num, const Vector2d & vec)
{
	return Vector2d(vec[0] * num, vec[1] * num);
}

bool Vector2d::operator==(const Vector2d & vec) const
{
	return ((vec[0] - Vector2d::EPSILON) <= m_data[0]) && (m_data[0] <= (vec[0] + Vector2d::EPSILON))
		&& ((vec[1] - Vector2d::EPSILON) <= m_data[1]) && (m_data[1] <= (vec[1] + Vector2d::EPSILON));
}

bool Vector2d::operator==(const Vector2f & vec) const
{
	return ((vec[0] - Vector2d::EPSILON) <= m_data[0]) && (m_data[0] <= (vec[0] + Vector2d::EPSILON))
		&& ((vec[1] - Vector2d::EPSILON) <= m_data[1]) && (m_data[1] <= (vec[1] + Vector2d::EPSILON));
}

bool Vector2d::operator==(const Vector2i & vec) const
{
	return ((vec[0] - Vector2d::EPSILON) <= m_data[0]) && (m_data[0] <= (vec[0] + Vector2d::EPSILON))
		&& ((vec[1] - Vector2d::EPSILON) <= m_data[1]) && (m_data[1] <= (vec[1] + Vector2d::EPSILON));
}

bool operator==(const Vector2i & veci, const Vector2d & vecd)
{
	return ((veci[0] - Vector2d::EPSILON) <= vecd[0]) && (vecd[0] <= (veci[0] + Vector2d::EPSILON))
		&& ((veci[1] - Vector2d::EPSILON) <= vecd[1]) && (vecd[1] <= (veci[1] + Vector2d::EPSILON));
}

bool operator==(const Vector2f & vecf, const Vector2d & vecd)
{
	return ((vecf[0] - Vector2d::EPSILON) <= vecd[0]) && (vecd[0] <= (vecf[0] + Vector2d::EPSILON))
		&& ((vecf[1] - Vector2d::EPSILON) <= vecd[1]) && (vecd[1] <= (vecf[1] + Vector2d::EPSILON));
}

bool Vector2d::operator!=(const Vector2d & vec) const
{
	return ((vec[0] - Vector2d::EPSILON) > m_data[0]) || (m_data[0] > (vec[0] + Vector2d::EPSILON))
		|| ((vec[1] - Vector2d::EPSILON) > m_data[1]) || (m_data[1] > (vec[1] + Vector2d::EPSILON));
}

bool Vector2d::operator!=(const Vector2f & vec) const
{
	return ((vec[0] - Vector2d::EPSILON) > m_data[0]) || (m_data[0] > (vec[0] + Vector2d::EPSILON))
		|| ((vec[1] - Vector2d::EPSILON) > m_data[1]) || (m_data[1] > (vec[1] + Vector2d::EPSILON));
}

bool Vector2d::operator!=(const Vector2i & vec) const
{
	return ((vec[0] - Vector2d::EPSILON) > m_data[0]) || (m_data[0] > (vec[0] + Vector2d::EPSILON))
		|| ((vec[1] - Vector2d::EPSILON) > m_data[1]) || (m_data[1] > (vec[1] + Vector2d::EPSILON));
}

bool operator!=(const Vector2i & veci, const Vector2d & vecd)
{
	return ((veci[0] - Vector2d::EPSILON) > vecd[0]) || (vecd[0] > (veci[0] + Vector2d::EPSILON))
		|| ((veci[1] - Vector2d::EPSILON) > vecd[1]) || (vecd[1] > (veci[1] + Vector2d::EPSILON));
}

bool operator!=(const Vector2f & vecf, const Vector2d & vecd)
{
	return ((vecf[0] - Vector2d::EPSILON) > vecd[0]) || (vecd[0] > (vecf[0] + Vector2d::EPSILON))
		|| ((vecf[1] - Vector2d::EPSILON) > vecd[1]) || (vecd[1] > (vecf[1] + Vector2d::EPSILON));
}
double Vector2d::LengthSquare() const
{
	return double(m_data[0] * m_data[0]) + double(m_data[1] * m_data[1]);
}

double Vector2d::Length() const
{
	return std::sqrt(double(m_data[0] * m_data[0]) + double(m_data[1] * m_data[1]));
}

void Vector2d::Normalize()
{
	double inverse_length = 1 / Length();
	Set(double(m_data[0] * inverse_length), double(m_data[1] * inverse_length));
}

Vector2d Vector2d::Normal() const
{
	double inverse_length = 1 / Length();
	return Vector2d(double(m_data[0] * inverse_length), double(m_data[1] * inverse_length));
}

